package com.wt.admin.service.language.impl;

import cn.hutool.core.util.ObjectUtil;
import com.wt.admin.code.language.QA2200;
import com.wt.admin.code.language.Tagging2100;
import com.wt.admin.config.ConstVar;
import com.wt.admin.config.socket.WebSocketSessionManager;
import com.wt.admin.domain.dto.language.*;
import com.wt.admin.domain.dto.model.ModelListDTO;
import com.wt.admin.domain.entity.language.ClassificationEntity;
import com.wt.admin.domain.entity.language.QAEntity;
import com.wt.admin.domain.vo.language.*;
import com.wt.admin.domain.vo.model.ModelListVO;
import com.wt.admin.domain.vo.socket.ProgressVO;
import com.wt.admin.domain.vo.socket.SocketVO;
import com.wt.admin.domain.vo.sys.UserVO;
import com.wt.admin.service.language.*;
import com.wt.admin.service.model.ModelListService;
import com.wt.admin.util.AssertUtil;
import com.wt.admin.util.PageUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j
@Service
public class LanguageProxyServiceImpl implements LanguageProxyService {

    @Resource
    private ClassificationService classificationService;
    @Resource
    private TaggingService taggingService;
    @Resource
    private QAService qaService;
    @Resource
    private LanguageTrainingService languageTrainingService;
    @Resource
    private SentenceConfigService sentenceConfigService;
    @Resource
    private ModelListService modelListService;


    @Override
    public void init(){
        log.debug("初始化关键词和QA数据");
        List<SentenceVO> list = taggingService.findByIds(null);
        WebSocketSessionManager.sendToAll(new SocketVO<ProgressVO>
                (ConstVar.Socket.PROGRESS,ProgressVO.set("初始化训练",0)).getJson());
        SentenceConfigDTO data = new SentenceConfigDTO();
        data.setTag("classification");
        SentenceConfigVO config = sentenceConfigService.findConfig(data, null);
        languageTrainingService.sentenceAndKeywordInit(list,config);
        log.debug("关键词初始化结束");
        data.setTag("qa");
        config = sentenceConfigService.findConfig(data, null);
        languageTrainingService.QAInit(config);
        log.debug("QA初始化结束");
    }


    @Override
    public ModelListVO classTest(ModelListDTO data) {
        // 加载模型
        // 测试模型
        return null;
    }

    @Override
    public ModelListVO qaTest(ModelListDTO data) {
        // 加载模型
        // 测试模型
        return null;
    }


    @Override
    public ClassTaggingVO taggingList(PageUtil.PageDTO<SentenceDTO> data) {
        return ClassTaggingVO.builder()
                .classificationVO(classificationService.list(null))
                .sentenceVO(taggingService.list(data))
                .build();
    }

    @Transactional
    @Override
    public ClassificationVO editClassAndSentence(ClassificationDTO data) {
        ClassificationVO classificationVO = classificationService.edit(data);
        taggingService.updateByClssKeywordObjBatch(classificationVO);
        return null;
    }

    @Override
    public ClassificationService getClassificationService() {
        return classificationService;
    }

    @Override
    public TaggingService getTaggingService() {
        return taggingService;
    }

    @Override
    public QAService getQAService() {
        return qaService;
    }

    @Override
    public QAListVO qaList(PageUtil.PageDTO<QADTO> data) {
        return QAListVO.builder()
                .qaList(qaService.list(data))
                .classificationVO(classificationService.list(null))
                .build();
    }

    @Async("newAsyncExecutor")
    @Override
    public void classTraining(ClassTrainingDTO data, UserVO userVO) {
        try {
            send("分类-训练样本", 0);
            // 根据ids 查询所有样本
            List<SentenceVO> list = taggingService.findByIds(data.getId());
            // 对样本标记状态更新
            languageTrainingService.classTraining(list,data.getConfig(),(flag) -> {
                if(!flag){
                    // 训练失败
                    log.debug("准确率 < 0.1 没有价值，因该修改配置参数去调整");
                    send( null, -100);
                    return null;
                }
                sentenceConfigService.updateConfig(data.getConfig(), userVO);
                taggingService.updateBatch(list);
                send( null, 100);
                return modelListService.addModel(userVO.getId(),data.getRemark(),data.getConfig(),ConstVar.ModelType.LANGUAGE);
            });
        }catch (Exception e){
            log.debug("训练失败 {}",e.getMessage());
            send( null, -100);
        }finally {
            ProgressVO.remove();
        }
    }

    @Override
    public ParseSentenceVO testTraining(String data, UserVO user) {
        AssertUtil.Str.isEmpty(data, Tagging2100.CODE_2105);
        ParseSentenceVO parseSentenceVO = new ParseSentenceVO();
        try {
            parseSentenceVO = languageTrainingService.parseSentence(data, "classification");
            ClassificationEntity classE = classificationService.findById(parseSentenceVO.getId());
            if (ObjectUtil.isEmpty(classE)) {
                return parseSentenceVO;
            }
            parseSentenceVO.setClassName(classE.getClassName());
        }catch (Exception e){
            e.printStackTrace();
            parseSentenceVO.setId(-1);
            parseSentenceVO.setClassName("未知数据");
        }
        return parseSentenceVO;
    }

    @Async("newAsyncExecutor")
    @Override
    public void qaTraining(QATrainingDTO data, UserVO user) {
        try {
            send("QA-训练样本", 0);
            // 根据ids 查询所有样本
            List<QAEntity> list = qaService.findByIds(data.getId());
            languageTrainingService.QATraining(list,data.getConfig(),(b) ->{
                sentenceConfigService.updateConfig(data.getConfig(), user);
                return modelListService.addModel(user.getId(),data.getRemark() ,data.getConfig(),ConstVar.ModelType.QA);
            });
            // 对样本标记状态更新
//            taggingService.updateBatch(list);
            send( null, 100);
        }catch (Exception e){
            send( null, -100);
            e.printStackTrace();
        }finally {
            ProgressVO.remove();
        }
    }

    @Override
    public QAParseSentenceVO qaTestTraining(String data, UserVO user) {
        AssertUtil.Str.isEmpty(data, QA2200.CODE_2206);
        QAParseSentenceVO qa = new QAParseSentenceVO();
        SentenceConfigDTO sentenceConfigDTO = new SentenceConfigDTO();
        sentenceConfigDTO.setTag("qa");
        SentenceConfigVO config = sentenceConfigService.findConfig(sentenceConfigDTO, user);
        qa.setAnswer(languageTrainingService.qaParseSentence(data,config));
        return qa;
    }

    @Override
    public SentenceConfigService getSentenceConfigService() {
        return this.sentenceConfigService;
    }


    private void send(String title, int progress){
        WebSocketSessionManager.sendToAll(new SocketVO<ProgressVO>
                (ConstVar.Socket.PROGRESS,ProgressVO.set(title,progress)).getJson());
    }

}
